@slidev/cli 52.15.0 → 52.15.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,5 @@
1
- import "./resolver-XedCEhxI.mjs";
2
- import { t as resolveViteConfigs } from "./shared-DDjOjYqG.mjs";
1
+ import "./resolver-BhqywfGz.mjs";
2
+ import { t as resolveViteConfigs } from "./shared-CmTSrQGO.mjs";
3
3
  import { join, resolve } from "node:path";
4
4
  import { build as build$1 } from "vite";
5
5
  import { existsSync } from "node:fs";
@@ -53,7 +53,7 @@ async function build(options, viteConfig = {}, args) {
53
53
  dev: true
54
54
  }));
55
55
  server.listen(port);
56
- const { exportSlides } = await import("./export-Dv3OTWhO.mjs");
56
+ const { exportSlides } = await import("./export-C2XL3OpJ.mjs");
57
57
  const tempDir = resolve(outDir, "temp");
58
58
  await fs$1.mkdir(tempDir, { recursive: true });
59
59
  await exportSlides({
@@ -94,7 +94,7 @@ async function build(options, viteConfig = {}, args) {
94
94
  "true",
95
95
  "auto"
96
96
  ].includes(options.data.config.download)) {
97
- const { exportSlides, getExportOptions } = await import("./export-Dv3OTWhO.mjs");
97
+ const { exportSlides, getExportOptions } = await import("./export-C2XL3OpJ.mjs");
98
98
  const port = 12445;
99
99
  const app = connect();
100
100
  const server = http.createServer(app);
package/dist/cli.mjs CHANGED
@@ -1,6 +1,6 @@
1
- import { i as resolveEntry, n as getRoots, r as isInstalledGlobally } from "./resolver-XedCEhxI.mjs";
2
- import { a as parser, c as resolveAddons, d as updateFrontmatterPatch, i as resolveOptions, l as version, o as getThemeMeta, s as resolveTheme, u as loadSetups } from "./shared-DDjOjYqG.mjs";
3
- import { t as createServer } from "./serve-BSv6omQ6.mjs";
1
+ import { i as resolveEntry, n as getRoots, r as isInstalledGlobally } from "./resolver-BhqywfGz.mjs";
2
+ import { a as parser, c as resolveAddons, d as updateFrontmatterPatch, i as resolveOptions, l as version, o as getThemeMeta, s as resolveTheme, u as loadSetups } from "./shared-CmTSrQGO.mjs";
3
+ import { t as createServer } from "./serve-CLoYUI-M.mjs";
4
4
  import path from "node:path";
5
5
  import process from "node:process";
6
6
  import fs from "node:fs/promises";
@@ -294,7 +294,7 @@ cli.command("build [entry..]", "Build hostable SPA", (args) => exportOptions(com
294
294
  describe: "enable the inspect plugin for debugging"
295
295
  }).strict().help(), async (args) => {
296
296
  const { entry, theme, base, download, out, inspect, "without-notes": withoutNotes, "router-mode": routerMode } = args;
297
- const { build } = await import("./build-BiWc4dXo.mjs");
297
+ const { build } = await import("./build-BZYW8gn1.mjs");
298
298
  for (const entryFile of entry) {
299
299
  const options = await resolveOptions({
300
300
  entry: entryFile,
@@ -359,7 +359,7 @@ cli.command("theme [subcommand]", "Theme related operations", (command) => {
359
359
  });
360
360
  cli.command("export [entry..]", "Export slides to PDF", (args) => exportOptions(commonOptions(args)).strict().help(), async (args) => {
361
361
  const { entry, theme } = args;
362
- const { exportSlides, getExportOptions } = await import("./export-Dv3OTWhO.mjs");
362
+ const { exportSlides, getExportOptions } = await import("./export-C2XL3OpJ.mjs");
363
363
  const candidatePort = await getPort(12445);
364
364
  let warned = false;
365
365
  for (const entryFile of entry) {
@@ -411,7 +411,7 @@ cli.command("export-notes [entry..]", "Export slide notes to PDF", (args) => arg
411
411
  type: "number",
412
412
  describe: "wait for the specified ms before exporting"
413
413
  }).strict().help(), async ({ entry, output, timeout, wait }) => {
414
- const { exportNotes } = await import("./export-Dv3OTWhO.mjs");
414
+ const { exportNotes } = await import("./export-C2XL3OpJ.mjs");
415
415
  const candidatePort = await getPort(12445);
416
416
  for (const entryFile of entry) {
417
417
  const options = await resolveOptions({ entry: entryFile }, "export");
@@ -1,4 +1,4 @@
1
- import { n as getRoots } from "./resolver-XedCEhxI.mjs";
1
+ import { n as getRoots } from "./resolver-BhqywfGz.mjs";
2
2
  import path, { dirname, relative } from "node:path";
3
3
  import process from "node:process";
4
4
  import fs from "node:fs/promises";
@@ -160,7 +160,7 @@ async function exportSlides({ port = 18724, total = 0, range: range$1, format =
160
160
  }
161
161
  {
162
162
  const frames = page.frames();
163
- await Promise.all(frames.map((frame) => frame.waitForLoadState()));
163
+ await Promise.all(frames.map((frame) => frame.waitForLoadState(void 0, { timeout })));
164
164
  }
165
165
  {
166
166
  const container = slide.locator("#mermaid-rendering-container");
@@ -304,9 +304,9 @@ async function exportSlides({ port = 18724, total = 0, range: range$1, format =
304
304
  if (!output.endsWith(".pdf")) output = `${output}.pdf`;
305
305
  return perSlide ? genPagePdfPerSlide() : genPagePdfOnePiece();
306
306
  }
307
- async function genPagePng(writeToDisk) {
307
+ async function genPagePng(writeToDisk, cleanOutput = true) {
308
308
  if (writeToDisk) {
309
- await fs.rm(writeToDisk, {
309
+ if (cleanOutput) await fs.rm(writeToDisk, {
310
310
  force: true,
311
311
  recursive: true
312
312
  });
@@ -315,7 +315,7 @@ async function exportSlides({ port = 18724, total = 0, range: range$1, format =
315
315
  return perSlide ? genPagePngPerSlide(writeToDisk) : genPagePngOnePiece(writeToDisk);
316
316
  }
317
317
  async function genPageMd() {
318
- const pngs = await genPagePng(dirname(output));
318
+ const pngs = await genPagePng(dirname(output), false);
319
319
  const content = slides.filter(({ index }) => pages.includes(index + 1)).map(({ title, index, note }) => pngs.filter(({ slideIndex }) => slideIndex === index).map(({ filename }) => `![${title || index + 1}](./${filename})\n\n`).join("") + (note ? `${note.trim()}\n\n` : "")).join("---\n\n");
320
320
  await fs.writeFile(ensureSuffix(".md", output), content);
321
321
  }
package/dist/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
- import "./resolver-XedCEhxI.mjs";
2
- import { a as parser, i as resolveOptions, n as ViteSlidevPlugin, r as createDataUtils } from "./shared-DDjOjYqG.mjs";
3
- import { t as createServer } from "./serve-BSv6omQ6.mjs";
1
+ import "./resolver-BhqywfGz.mjs";
2
+ import { a as parser, i as resolveOptions, n as ViteSlidevPlugin, r as createDataUtils } from "./shared-CmTSrQGO.mjs";
3
+ import { t as createServer } from "./serve-CLoYUI-M.mjs";
4
4
 
5
5
  export { ViteSlidevPlugin, createDataUtils, createServer, parser, resolveOptions };
@@ -14,6 +14,7 @@ import { findClosestPkgJsonPath, findDepPkgJsonPath } from "vitefu";
14
14
 
15
15
  //#region node/resolver.ts
16
16
  const RE_PATH_SEPARATOR = /[/\\]/;
17
+ const RE_SAFE_PKG_NAME = /^(?:@[a-z0-9-~][a-z0-9-._~]*\/)?[a-z0-9-~][a-z0-9-._~]*$/;
17
18
  const cliRoot = fileURLToPath(new URL("..", import.meta.url));
18
19
  const isInstalledGlobally = {};
19
20
  /**
@@ -93,6 +94,7 @@ function createResolver(type, officials) {
93
94
  if (name[0] === "/") return [name, name];
94
95
  if (name.startsWith("@/")) return [name, resolve(userRoot, name.slice(2))];
95
96
  if (name[0] === "." || name[0] !== "@" && name.includes("/")) return [name, resolve(dirname(importer), name)];
97
+ if (!RE_SAFE_PKG_NAME.test(name)) throw new Error(`Invalid ${type} name "${name}". Only valid npm package names are allowed.`);
96
98
  {
97
99
  const possiblePkgNames = [name];
98
100
  if (!name.includes("/") && !name.startsWith("@")) possiblePkgNames.unshift(`@slidev/${type}-${name}`, `slidev-${type}-${name}`);
@@ -1,4 +1,4 @@
1
- import { t as resolveViteConfigs } from "./shared-DDjOjYqG.mjs";
1
+ import { t as resolveViteConfigs } from "./shared-CmTSrQGO.mjs";
2
2
  import { join } from "node:path";
3
3
  import process from "node:process";
4
4
  import { createServer } from "vite";
@@ -1,9 +1,9 @@
1
- import { a as resolveImportPath, c as toAtFS, i as resolveEntry, n as getRoots, o as resolveImportUrl, r as isInstalledGlobally, s as resolveSourceFiles, t as createResolver } from "./resolver-XedCEhxI.mjs";
1
+ import { a as resolveImportPath, c as toAtFS, i as resolveEntry, n as getRoots, o as resolveImportUrl, r as isInstalledGlobally, s as resolveSourceFiles, t as createResolver } from "./resolver-BhqywfGz.mjs";
2
2
  import { builtinModules } from "node:module";
3
- import path, { basename, dirname, join, relative, resolve } from "node:path";
4
- import { loadConfigFromFile, mergeConfig } from "vite";
3
+ import path, { basename, dirname, join, relative, resolve, win32 } from "node:path";
4
+ import { loadConfigFromFile, mergeConfig, parseSync } from "vite";
5
5
  import MarkdownExit from "markdown-exit";
6
- import fs, { existsSync } from "node:fs";
6
+ import fs, { existsSync, realpathSync } from "node:fs";
7
7
  import fs$1, { readFile } from "node:fs/promises";
8
8
  import { fileURLToPath, pathToFileURL } from "node:url";
9
9
  import { ensureSuffix, isString, isTruthy, notNullish, objectEntries, objectMap, range, slash, uniq } from "@antfu/utils";
@@ -70,6 +70,7 @@ function MarkdownItLink(md) {
70
70
  const RE_WHITESPACE_ONLY = /^\s*$/;
71
71
  const RE_QUOTED_STRING = /^(['"])(.*)\1$/;
72
72
  const RE_WHITESPACE = /\s+/g;
73
+ const RE_WINDOWS_DRIVE = /^[A-Z]:\//i;
73
74
  let jiti;
74
75
  function loadModule(absolutePath) {
75
76
  jiti ??= createJiti(fileURLToPath(import.meta.url), { moduleCache: false });
@@ -131,11 +132,21 @@ function getBodyJson(req) {
131
132
  });
132
133
  });
133
134
  }
134
- function makeAbsoluteImportGlob(self, globs, options = {}) {
135
- const relativeGlobs = globs.map((glob) => `${slash(relative(self, glob))}`);
135
+ function getImportGlobRelativePath(from, to) {
136
+ const normalizedFrom = slash(from);
137
+ const normalizedTo = slash(to);
138
+ return slash(RE_WINDOWS_DRIVE.test(normalizedFrom) || RE_WINDOWS_DRIVE.test(normalizedTo) ? win32.relative(normalizedFrom, normalizedTo) : relative(normalizedFrom, normalizedTo));
139
+ }
140
+ function makeAbsoluteImportGlob(self, globs, options = {}, baseRoot) {
141
+ const root = baseRoot && globs.some((glob) => RE_WINDOWS_DRIVE.test(slash(glob))) ? baseRoot : void 0;
142
+ const relativeGlobs = globs.map((glob) => {
143
+ const relativeGlob = getImportGlobRelativePath(root ?? self, glob);
144
+ return root && !relativeGlob.startsWith(".") && !RE_WINDOWS_DRIVE.test(relativeGlob) ? `./${relativeGlob}` : relativeGlob;
145
+ });
136
146
  const opts = {
137
147
  eager: true,
138
148
  exhaustive: true,
149
+ ...root ? { base: "/" } : {},
139
150
  ...options
140
151
  };
141
152
  return `import.meta.glob(${JSON.stringify(relativeGlobs)}, ${JSON.stringify(opts)})`;
@@ -462,6 +473,158 @@ function createIconsPlugin(options, pluginOptions) {
462
473
  });
463
474
  }
464
475
 
476
+ //#endregion
477
+ //#region node/virtual/deprecated.ts
478
+ /**
479
+ * Kept for backward compatibility, use #slidev/slides instead
480
+ *
481
+ * @deprecated
482
+ */
483
+ const templateLegacyRoutes = {
484
+ id: "/@slidev/routes",
485
+ getContent() {
486
+ return [`export { slides } from '#slidev/slides'`, `console.warn('[slidev] #slidev/routes is deprecated, use #slidev/slides instead')`].join("\n");
487
+ }
488
+ };
489
+ /**
490
+ * Kept for backward compatibility, use #slidev/title-renderer instead
491
+ *
492
+ * @deprecated
493
+ */
494
+ const templateLegacyTitles = {
495
+ id: "/@slidev/titles.md",
496
+ getContent() {
497
+ return `
498
+ <script setup lang="ts">
499
+ import TitleRenderer from '#slidev/title-renderer'
500
+ defineProps<{ no: number | string }>()
501
+ console.warn('/@slidev/titles.md is deprecated, import from #slidev/title-renderer instead')
502
+ <\/script>
503
+
504
+ <TitleRenderer :no="no" />
505
+ `;
506
+ }
507
+ };
508
+
509
+ //#endregion
510
+ //#region node/virtual/titles.ts
511
+ const templateTitleRendererMd = {
512
+ id: "/@slidev/title-renderer.md",
513
+ getContent({ data }) {
514
+ const lines = data.slides.map(({ title }, i) => `<template ${i === 0 ? "v-if" : "v-else-if"}="no === ${i + 1}">\n\n${title}\n\n</template>`);
515
+ lines.push(`<script setup lang="ts">`, `import { useSlideContext } from '@slidev/client/context.ts'`, `import { computed } from 'vue'`, `const props = defineProps<{ no?: number | string }>()`, `const { $page } = useSlideContext()`, `const no = computed(() => +(props.no ?? $page.value))`, `<\/script>`);
516
+ return lines.join("\n");
517
+ }
518
+ };
519
+ const templateTitleRenderer = {
520
+ id: "/@slidev/title-renderer",
521
+ async getContent() {
522
+ return "export { default } from \"/@slidev/title-renderer.md\"";
523
+ }
524
+ };
525
+
526
+ //#endregion
527
+ //#region node/vite/importGuard.ts
528
+ const virtualSlideMarkdownIds = new Set([templateTitleRendererMd.id, templateLegacyTitles.id]);
529
+ function createSlideImportGuardPlugin() {
530
+ let config;
531
+ let allowRoots = [];
532
+ return {
533
+ name: "slidev:slide-import-guard",
534
+ configResolved(resolved) {
535
+ config = resolved;
536
+ allowRoots = config.server.fs.allow.map(normalizeFsPath);
537
+ },
538
+ async transform(code, id$2) {
539
+ if (!isSlideMarkdownId(id$2) || !config?.server.fs.strict) return null;
540
+ const importer = filePathFromId(id$2) ?? id$2;
541
+ await Promise.all(extractImportSources(code, id$2).map(async ({ value, start }) => {
542
+ const resolved = await this.resolve(value, importer, { skipSelf: true });
543
+ if (!resolved || resolved.external) return;
544
+ const filePath = filePathFromId(resolved.id);
545
+ if (!filePath) return;
546
+ const normalized = normalizeFsPath(filePath);
547
+ if (isAllowedFile(normalized, allowRoots)) return;
548
+ if (isBareImport(value) && isDependencyFile(normalized)) return;
549
+ this.error(`[slidev] Import "${value}" from slide Markdown resolves outside of Vite server.fs.allow: ${normalized}`, start);
550
+ }));
551
+ return null;
552
+ }
553
+ };
554
+ }
555
+ function isSlideMarkdownId(id$2) {
556
+ const clean = cleanUrl$1(id$2);
557
+ return regexSlideSourceId.test(clean) || virtualSlideMarkdownIds.has(clean);
558
+ }
559
+ function filePathFromId(id$2) {
560
+ const clean = cleanUrl$1(id$2);
561
+ if (clean.startsWith("file://")) return fileURLToPath(clean);
562
+ if (clean.startsWith("/@fs/")) return clean.slice(4);
563
+ if (clean.startsWith("/@")) return null;
564
+ if (path.isAbsolute(clean)) return clean;
565
+ return null;
566
+ }
567
+ function isAllowedFile(filePath, allowRoots) {
568
+ return allowRoots.some((root) => isFileInRoot(root, filePath));
569
+ }
570
+ function extractImportSources(code, id$2) {
571
+ const result = parseSync(id$2, code);
572
+ const sources = [];
573
+ for (const item of result.module.staticImports) sources.push({
574
+ value: item.moduleRequest.value,
575
+ start: item.moduleRequest.start
576
+ });
577
+ for (const item of result.module.staticExports) for (const entry of item.entries) if (entry.moduleRequest) sources.push({
578
+ value: entry.moduleRequest.value,
579
+ start: entry.moduleRequest.start
580
+ });
581
+ for (const item of result.module.dynamicImports) {
582
+ const source = parseStringLiteral(code.slice(item.moduleRequest.start, item.moduleRequest.end));
583
+ if (source) sources.push({
584
+ value: source,
585
+ start: item.moduleRequest.start
586
+ });
587
+ }
588
+ return sources;
589
+ }
590
+ function cleanUrl$1(id$2) {
591
+ return id$2.replace(/[?#].*$/, "");
592
+ }
593
+ function normalizeFsPath(filePath) {
594
+ const absolute = path.resolve(filePath);
595
+ if (!existsSync(absolute)) return normalizeMissingFsPath(absolute);
596
+ return realpathSync.native(absolute);
597
+ }
598
+ function normalizeMissingFsPath(filePath) {
599
+ const dir = path.dirname(filePath);
600
+ if (dir === filePath) return filePath;
601
+ if (existsSync(dir)) return path.join(realpathSync.native(dir), path.basename(filePath));
602
+ return path.join(normalizeMissingFsPath(dir), path.basename(filePath));
603
+ }
604
+ function isFileInRoot(root, filePath) {
605
+ const relative$1 = path.relative(root, filePath);
606
+ return relative$1 === "" || !!relative$1 && !relative$1.startsWith("..") && !path.isAbsolute(relative$1);
607
+ }
608
+ function isDependencyFile(filePath) {
609
+ return filePath.split(/[\\/]/).includes("node_modules");
610
+ }
611
+ function isBareImport(source) {
612
+ return /^(?![a-z]:)[\w@](?!.*:\/\/)/i.test(source);
613
+ }
614
+ function parseStringLiteral(raw) {
615
+ const trimmed = raw.trim();
616
+ const quote = trimmed[0];
617
+ if (quote !== "\"" && quote !== "'" && quote !== "`") return null;
618
+ if (trimmed.at(-1) !== quote) return null;
619
+ if (quote === "`" && trimmed.includes("${")) return null;
620
+ try {
621
+ if (quote === "\"") return JSON.parse(trimmed);
622
+ return JSON.parse(`"${trimmed.slice(1, -1).replace(/"/g, "\\\"")}"`);
623
+ } catch {
624
+ return trimmed.slice(1, -1);
625
+ }
626
+ }
627
+
465
628
  //#endregion
466
629
  //#region node/vite/inspect.ts
467
630
  async function createInspectPlugin(options, pluginOptions) {
@@ -522,7 +685,7 @@ function createLayoutWrapperPlugin({ data, utils }) {
522
685
 
523
686
  //#endregion
524
687
  //#region package.json
525
- var version = "52.15.0";
688
+ var version = "52.15.2";
526
689
 
527
690
  //#endregion
528
691
  //#region node/integrations/addons.ts
@@ -1085,13 +1248,13 @@ function MarkdownItKatex(md, options) {
1085
1248
  const id$1 = "/@slidev/conditional-styles";
1086
1249
  const templateConditionalStyles = {
1087
1250
  id: id$1,
1088
- async getContent({ data, roots }) {
1251
+ async getContent({ data, roots, userRoot }) {
1089
1252
  const imports = [];
1090
1253
  for (const root of roots) imports.push(makeAbsoluteImportGlob(id$1, [
1091
1254
  join(root, "styles/index.{ts,js,css}"),
1092
1255
  join(root, "styles.{ts,js,css}"),
1093
1256
  join(root, "style.{ts,js,css}")
1094
- ]));
1257
+ ], {}, userRoot));
1095
1258
  if (data.features.katex) imports.push(`import "${await resolveImportUrl("katex/dist/katex.min.css")}"`);
1096
1259
  return imports.join("\n");
1097
1260
  }
@@ -1112,51 +1275,18 @@ const templateConfigs = {
1112
1275
  }
1113
1276
  };
1114
1277
 
1115
- //#endregion
1116
- //#region node/virtual/deprecated.ts
1117
- /**
1118
- * Kept for backward compatibility, use #slidev/slides instead
1119
- *
1120
- * @deprecated
1121
- */
1122
- const templateLegacyRoutes = {
1123
- id: "/@slidev/routes",
1124
- getContent() {
1125
- return [`export { slides } from '#slidev/slides'`, `console.warn('[slidev] #slidev/routes is deprecated, use #slidev/slides instead')`].join("\n");
1126
- }
1127
- };
1128
- /**
1129
- * Kept for backward compatibility, use #slidev/title-renderer instead
1130
- *
1131
- * @deprecated
1132
- */
1133
- const templateLegacyTitles = {
1134
- id: "/@slidev/titles.md",
1135
- getContent() {
1136
- return `
1137
- <script setup lang="ts">
1138
- import TitleRenderer from '#slidev/title-renderer'
1139
- defineProps<{ no: number | string }>()
1140
- console.warn('/@slidev/titles.md is deprecated, import from #slidev/title-renderer instead')
1141
- <\/script>
1142
-
1143
- <TitleRenderer :no="no" />
1144
- `;
1145
- }
1146
- };
1147
-
1148
1278
  //#endregion
1149
1279
  //#region node/virtual/global-layers.ts
1150
1280
  const id = `/@slidev/global-layers`;
1151
1281
  const templateGlobalLayers = {
1152
1282
  id,
1153
- getContent({ roots }) {
1283
+ getContent({ roots, userRoot }) {
1154
1284
  function* getComponent(name, names) {
1155
1285
  yield `const ${name}Components = [\n`;
1156
1286
  for (const root of roots) {
1157
1287
  const globs = names.map((name$1) => join(root, `${name$1}.{ts,js,vue}`));
1158
1288
  yield " Object.values(";
1159
- yield makeAbsoluteImportGlob(id, globs, { import: "default" });
1289
+ yield makeAbsoluteImportGlob(id, globs, { import: "default" }, userRoot);
1160
1290
  yield ")[0],\n";
1161
1291
  }
1162
1292
  yield `].filter(Boolean)\n`;
@@ -1275,9 +1405,9 @@ function createSetupTemplate(name) {
1275
1405
  const id$2 = `/@slidev/setups/${name}`;
1276
1406
  return {
1277
1407
  id: id$2,
1278
- getContent({ roots }) {
1408
+ getContent({ roots, userRoot }) {
1279
1409
  return `export default [${roots.map((root) => {
1280
- return `Object.values(${makeAbsoluteImportGlob(id$2, [join(root, `setup/${name}.{ts,js,mts,mjs}`)], { import: "default" })})[0]`;
1410
+ return `Object.values(${makeAbsoluteImportGlob(id$2, [join(root, `setup/${name}.{ts,js,mts,mjs}`)], { import: "default" }, userRoot)})[0]`;
1281
1411
  }).join(", ")}].filter(Boolean)`;
1282
1412
  }
1283
1413
  };
@@ -1334,23 +1464,6 @@ const templateSlides = {
1334
1464
  }
1335
1465
  };
1336
1466
 
1337
- //#endregion
1338
- //#region node/virtual/titles.ts
1339
- const templateTitleRendererMd = {
1340
- id: "/@slidev/title-renderer.md",
1341
- getContent({ data }) {
1342
- const lines = data.slides.map(({ title }, i) => `<template ${i === 0 ? "v-if" : "v-else-if"}="no === ${i + 1}">\n\n${title}\n\n</template>`);
1343
- lines.push(`<script setup lang="ts">`, `import { useSlideContext } from '@slidev/client/context.ts'`, `import { computed } from 'vue'`, `const props = defineProps<{ no?: number | string }>()`, `const { $page } = useSlideContext()`, `const no = computed(() => +(props.no ?? $page.value))`, `<\/script>`);
1344
- return lines.join("\n");
1345
- }
1346
- };
1347
- const templateTitleRenderer = {
1348
- id: "/@slidev/title-renderer",
1349
- async getContent() {
1350
- return "export { default } from \"/@slidev/title-renderer.md\"";
1351
- }
1352
- };
1353
-
1354
1467
  //#endregion
1355
1468
  //#region node/virtual/index.ts
1356
1469
  const templates = [
@@ -2757,6 +2870,7 @@ function ViteSlidevPlugin(options, pluginOptions = {}, serverOptions = {}) {
2757
2870
  createLayoutWrapperPlugin(options),
2758
2871
  createContextInjectionPlugin(),
2759
2872
  createVuePlugin(options, pluginOptions),
2873
+ createSlideImportGuardPlugin(),
2760
2874
  createHmrPatchPlugin(),
2761
2875
  createComponentsPlugin(options, pluginOptions),
2762
2876
  createIconsPlugin(options, pluginOptions),
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@slidev/cli",
3
3
  "type": "module",
4
- "version": "52.15.0",
4
+ "version": "52.15.2",
5
5
  "description": "Presentation slides for developers",
6
6
  "author": "Anthony Fu <anthonyfu117@hotmail.com>",
7
7
  "license": "MIT",
@@ -111,9 +111,9 @@
111
111
  "vue": "^3.5.33",
112
112
  "yaml": "^2.8.3",
113
113
  "yargs": "^18.0.0",
114
- "@slidev/client": "52.15.0",
115
- "@slidev/parser": "52.15.0",
116
- "@slidev/types": "52.15.0"
114
+ "@slidev/parser": "52.15.2",
115
+ "@slidev/types": "52.15.2",
116
+ "@slidev/client": "52.15.2"
117
117
  },
118
118
  "devDependencies": {
119
119
  "@hedgedoc/markdown-it-plugins": "^2.1.4",